package org.teamh.gui.ingame;

import static org.lwjgl.opengl.GL11.*;

import java.io.File;
import java.nio.FloatBuffer;
import java.util.HashMap;

import org.lwjgl.BufferUtils;
import org.lwjgl.util.glu.Disk;
import org.teamh.connection.json.command.JsonSender;
import org.teamh.gui.engine.model.Model;
import org.teamh.gui.engine.model.TextureLoader;

import org.teamh.gui.engine.texture.Texture;
import org.teamh.gui.engine.texture.TextureLoaderCAC;
import org.teamh.gui.ingame.data_structure.SafeList.Element;
import org.teamh.logic.datamodel.Cell;
import org.teamh.logic.datamodel.Creep;
import org.teamh.logic.datamodel.DatamodelManager;
import org.teamh.logic.datamodel.Tower;
import org.teamh.logic.datamodel.TowerDescription;

public class Map {
	private static final float OBJECT_DISTANCE_Y=0.001f;
	private static final float GRID_DISTANCE_Y=0.00101f;
	private static final float TILE_SIZE=1 / 16f;
	private static final float CELL_SIZE=1 / 16f;
	private static final float MOUSE_STRIP_LENGHT= 1 / 16f;
	private static final float MOUSE_STRIP_DISTANCE_Y=0.00211f;
	private static final float BLENDING=0.4f;
	
	private int rotateCreep=0;
	private float q1 = 1f;
	private float q2 = 1f;
	private float q3 = 1f;
	private float q4 = 1f;
	private Disk rangeDiskIn = new Disk();
	private Disk rangeDiskOut = new Disk();

	private DatamodelManager model;
	private Information info;
	private LoadTowers tower;
	private LoadCreeps creep;
	private String selectedTower;

	private boolean towerChoosed;
	private boolean buildTower;
	private boolean showCells;

	private Model model_object;
	private Model model_colored;
	
	private int mousePosX;
	private int mousePosZ;

	private File textureFile;
	private Texture texture;
	private int crateTexture;
	private IngameFunctions ingameFunctions;
	private float range;

	private int pickX = -30;
	private int pickZ = -30;
	private boolean colorPicking = false;
	
	private FloatBuffer material;

	public Map(IngameFunctions ingameFunctions) {
		texture = TextureLoaderCAC.getTexture("res/img/mapeditor/map_summer.jpg");
		crateTexture = TextureLoader.loadTexture("res/img/ingame/crate.png", GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR, true);
		model = ingameFunctions.getGui().getStart().getLogic().getManager();
		this.ingameFunctions = ingameFunctions;
		tower=new LoadTowers();
		creep=new LoadCreeps();
		
		material = BufferUtils.createFloatBuffer(4);
	}
	
	public void init() {
		if(textureFile == null) {
			return;
		}
		texture = TextureLoaderCAC.getTexture(textureFile);
		setColors();
	}
	
	public void setColors() {
		int players = ingameFunctions.getGui().getStart().getLogic().getGame().getNumPlayers();
		if (players == 1){
			q1 = 1.0f;
			q2 = 0.1f;
			q3 = 0.1f;
			q4 = 0.1f;
		} else if (players == 2) {
			q1 = 1.0f;
			q2 = 1.0f;
			q3 = 0.1f;
			q4 = 0.1f;
		} else if (players == 3) {
			q1 = 1.0f;
			q2 = 1.0f;
			q3 = 0.1f;
			q4 = 1.0f;
		} else {
			q1 = 1.0f;
			q2 = 1.0f;
			q3 = 1.0f;
			q4 = 1.0f;
		}
	}

	public void renderFields() {
		if(!showCells)
			
			return;
		try {
			
			HashMap<String, Cell> cells = model.getCells();
			for (Cell c: cells.values()) {
				int x = c.getX();
				int y = c.getY();
				
				if (c.getMap().getTile().getPosition().equals(ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().getMyTile())) {
					if (c.getType().contains("WALKABLE")) {
						drawWalkable(x, y, c.getMap().getTile().getPosition());
						continue;
					}
					if (c.getType().contains("NONE")) {
						drawNoneField(x, y, c.getMap().getTile().getPosition());
						continue;
					}
					if (c.getType().contains("TOWER")) {
						drawTowerField(x, y, c.getMap().getTile().getPosition());
						continue;
					}
				}
					
			}

		} catch (Exception e) {
		}
	}

	public void renderForPicking() {
		glBegin(GL_QUADS);
		{
			glVertex3f(-30, 0, -30);
			glVertex3f(-30, 0, 30);
			glVertex3f(30, 0, 30);
			glVertex3f(30, 0, -30);
		}
		glEnd();
	}

	public void render(float timeElapsed) {
		glEnable(GL_LIGHTING);
		drawCreep(timeElapsed);
		glDisable(GL_LIGHTING);
		
		texture.bind();
		glColor3f(q1, q1, q1);
		glBegin(GL_QUADS);
		{
			glTexCoord2f(0, 0);
			glVertex3f(-1, 0, -1);
			glTexCoord2f(0, 1);
			glVertex3f(-1, 0, 0);
			glTexCoord2f(1, 1);
			glVertex3f(0, 0, 0);
			glTexCoord2f(1, 0);
			glVertex3f(0, 0, -1);

		}
		glEnd();
		glDisable(GL_TEXTURE_2D);

		glEnable(GL_TEXTURE_2D);
		glColor3f(q2, q2, q2);
		glBegin(GL_QUADS);
		{
			
			glTexCoord2f(0, 1);
			glVertex3f(0, 0, -1);
			glTexCoord2f(1, 1);
			glVertex3f(0, 0, 0);
			glTexCoord2f(1, 0);
			glVertex3f(1, 0, 0);
			glTexCoord2f(0, 0);
			glVertex3f(1, 0, -1);

		}
		glEnd();
		glDisable(GL_TEXTURE_2D);

		glEnable(GL_TEXTURE_2D);
		glColor3f(q3, q3, q3);
		glBegin(GL_QUADS);
		{
			glTexCoord2f(1, 0);
			glVertex3f(-1, 0, 0);
			glTexCoord2f(0, 0);
			glVertex3f(-1, 0, 1);
			glTexCoord2f(0, 1);
			glVertex3f(0, 0, 1);
			glTexCoord2f(1, 1);
			glVertex3f(0, 0, 0);

		}
		glEnd();
		glDisable(GL_TEXTURE_2D);

		glEnable(GL_TEXTURE_2D);
		glColor3f(q4, q4, q4);
		glBegin(GL_QUADS);
		{
			glTexCoord2f(1, 1);
			glVertex3f(0, 0, 0);
			glTexCoord2f(1, 0);
			glVertex3f(0, 0, 1);
			glTexCoord2f(0, 0);
			glVertex3f(1, 0, 1);
			glTexCoord2f(0, 1);
			glVertex3f(1, 0, 0);

		}
		glEnd();
		glDisable(GL_TEXTURE_2D);
		
		drawMousePosition(pickX, pickZ);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		drawGrid();
		renderBlock();
		if(towerChoosed){
			renderFields();
		}
		glDisable(GL_BLEND);
		
		if(model_object != null) {
			showTower(model_object, model_colored);
		}
	}
	
	private void renderBlock() {
		glColor3f(1, 1, 1);
		glEnable(GL_TEXTURE_2D);
		glBindTexture(GL_TEXTURE_2D, crateTexture);
		glBegin(GL_QUAD_STRIP);
		{
			float height = 2;
			
			glTexCoord2f(0, 0);
			glVertex3f(-1, 0, 1);
			glTexCoord2f(0, 1);
			glVertex3f(-1, -height, 1);
			
			glTexCoord2f(1, 0);
			glVertex3f(1, 0, 1);
			glTexCoord2f(1, 1);
			glVertex3f(1, -height, 1);
			
			glTexCoord2f(2, 0);
			glVertex3f(1, 0, -1);
			glTexCoord2f(2, 1);
			glVertex3f(1, -height, -1);
			
			glTexCoord2f(3, 0);
			glVertex3f(-1, 0, -1);
			glTexCoord2f(3, 1);
			glVertex3f(-1, -height, -1);
			
			glTexCoord2f(4, 0);
			glVertex3f(-1, 0, 1);
			glTexCoord2f(4, 1);
			glVertex3f(-1, -height, 1);
		}
		glEnd();
		glDisable(GL_TEXTURE_2D);
	}

	public void showTower(Model tower_object, Model tower_colored) {
		
		HashMap<String, TowerDescription> tower = model.getTowerDescriptions();
		for(String towerDescription: tower.keySet()){
			
			if(tower.get(towerDescription).getName().contains(selectedTower)&&tower.get(towerDescription).getLevel()==1)
				range=(float)tower.get(towerDescription).getRange();
		}
		glEnable(GL_TEXTURE_2D);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glEnable(GL_LIGHTING);
		glColor4f(1, 1, 1, 0.5f);
		setColor("ffffff");
		glPushMatrix();
		{
			glScalef(CELL_SIZE, CELL_SIZE, CELL_SIZE);
			glRotatef(90, 0, 1, 0);
			glTranslatef(-mousePosZ + (mousePosZ > 0 ? 1 : 0) - 0.5f, 0, mousePosX - (mousePosX > 0 ? 1 : 0) + 0.5f);
			tower_object.render();
			setColor("00ff00");
			tower_colored.render();
			glTranslatef(0, 0.02f, 0);
			renderRange();
		}
		glPopMatrix();
		glDisable(GL_LIGHTING);
		glDisable(GL_BLEND);
	}
	
	private void renderRange() {
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_BLEND);
		glDisable(GL_LIGHTING);
		glEnable(GL_BLEND);
		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
		glColor4f(1, 0, 0, 0.5f);
		glPushMatrix();
		{
			glRotatef(90, 1, 0, 0);
			rangeDiskIn.draw(0, range-0.08f, 60, 1);
			glColor4f(0, 1, 0, 0.7f);
			rangeDiskIn.draw(range-0.08f, range, 60, 1);
			glDisable(GL_BLEND);
		}
		glPopMatrix();
		glEnable(GL_BLEND);
	}
	
	private void drawTowerField(int y, int x, String tower) {
		glColor4f(0, 1, 0, BLENDING);
		if (tower.contains("TOP_LEFT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
			}
			glEnd();
			return;
		}
		if (tower.contains("TOP_RIGHT")) {
			glBegin(GL_QUADS);
			{

				glVertex3f((y) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
			}
			glEnd();
			return;
		}
		if (tower.contains("BOTTOM_LEFT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x) * TILE_SIZE);
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x) * TILE_SIZE);
			}
			glEnd();
			return;
		}
		if (tower.contains("BOTTOM_RIGHT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f(y * TILE_SIZE, OBJECT_DISTANCE_Y, x * TILE_SIZE);
				glVertex3f(y * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, x * TILE_SIZE);
			}
			glEnd();
			return;
		}
	}

	private void drawWalkable(int y, int x, String quadrant) {
		glColor4f(0, 0, 1, BLENDING);
		if (quadrant.contains("TOP_LEFT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
			}
			glEnd();
			return;
		}
		if (quadrant.contains("TOP_RIGHT")) {
			glBegin(GL_QUADS);
			{

				glVertex3f((y) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
			}
			glEnd();
			return;
		}
		if (quadrant.contains("BOTTOM_LEFT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x) * TILE_SIZE);
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x) * TILE_SIZE);
			}
			glEnd();
			return;
		}
		if (quadrant.contains("BOTTOM_RIGHT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f(y * TILE_SIZE, OBJECT_DISTANCE_Y, x * TILE_SIZE);
				glVertex3f(y * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, x * TILE_SIZE);
			}
			glEnd();
			return;
		}
	}

	private void drawNoneField(int y, int x, String nonField) {
		glColor4f(1, 0, 0, BLENDING);
		if (nonField.contains("TOP_LEFT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
			}
			glEnd();
			
			return;
		}
		if (nonField.contains("TOP_RIGHT")) {
			glBegin(GL_QUADS);
			{

				glVertex3f((y) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
				glVertex3f((y) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 15) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x - 16) * TILE_SIZE);
			}
			glEnd();
			
			return;
		}
		if (nonField.contains("BOTTOM_LEFT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x) * TILE_SIZE);
				glVertex3f((y - 16) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y - 15) * TILE_SIZE, OBJECT_DISTANCE_Y, (x) * TILE_SIZE);
			}
			glEnd();

			return;
		}
		if (nonField.contains("BOTTOM_RIGHT")) {
			glBegin(GL_QUADS);
			{
				glVertex3f(y * TILE_SIZE, OBJECT_DISTANCE_Y, x * TILE_SIZE);
				glVertex3f(y * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, (x + 1) * TILE_SIZE);
				glVertex3f((y + 1) * TILE_SIZE, OBJECT_DISTANCE_Y, x * TILE_SIZE);
			}
			glEnd();

			return;
		}
	}

	private void drawGrid() {
		float x = -1;
		float y = 1;
		float z = -1;
		for (int i = 0; i <= 32; i++) {
			drawLinehorizontal(x, y);
			x += TILE_SIZE;
		}
		x = -1;
		z = -1;
		for (int i = 0; i <= 32; i++) {
			drawLineVertical(x, z);
			z += TILE_SIZE;
		}
	}

	private void drawLinehorizontal(float x, float z) {
		glColor4f(0.1f, 0.1f, 0.1f, BLENDING);
		glBegin(GL_LINE_STRIP);
		glVertex3f(x, GRID_DISTANCE_Y, z);
		glVertex3f(x, GRID_DISTANCE_Y, -z);
		glEnd();
	}

	private void drawLineVertical(float x, float z) {
		glColor4f(0.1f, 0.1f, 0.1f, BLENDING);
		glBegin(GL_LINE_STRIP);
		glVertex3f(x, GRID_DISTANCE_Y, z);
		glVertex3f(-x, GRID_DISTANCE_Y, z);
		glEnd();
	}

	private void drawMousePosition(int x, int z) {
		mousePosX=x;
		mousePosZ=z;
		if(x < -20) {
			return;
		}
		
		if (x > 0 && z > 0) {
			glColor3f(0, 1, 0);
			glBegin(GL_LINE_STRIP);
			{
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z - 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x - 1) * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z - 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x - 1) * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
			}
			glEnd();
			return;
		}
		if (x < 0 && z < 0) {
			glColor3f(0, 1, 0);
			glBegin(GL_LINE_STRIP);
			{
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z + 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x + 1) * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z + 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x + 1) * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
			}
			glEnd();
			return; 
		}

		if (x < 0 && z > 0) {
			glColor3f(0, 1, 0);
			glBegin(GL_LINE_STRIP);
			{
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z - 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x + 1) * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z - 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x + 1) * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
			}
			glEnd();
			return;
		}
		if (x > 0 && z < 0) {
			glColor3f(0, 1, 0);
			glBegin(GL_LINE_STRIP);
			{
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z + 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x - 1) *MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, (z + 1) * MOUSE_STRIP_LENGHT);
				glVertex3d((x - 1) * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
				glVertex3d(x * MOUSE_STRIP_LENGHT, MOUSE_STRIP_DISTANCE_Y, z * MOUSE_STRIP_LENGHT);
			}
			glEnd();
			return;
		}
	}
	public void tile(int x, int z){
		String tile=ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().getMyTile();
		if(tile=="TOP_LEFT"){
			if(x<0&&z<0){
				int x_new= 17-Math.abs(x)-1;
				int z_new= 17-Math.abs(z)-1;
				checkBuildTower(tile, x_new,z_new);
				return;
			}
		}
		if(tile=="TOP_RIGHT"){
			if(z<0&&x>0){
				int x_new= Math.abs(x)-1;
				int z_new= 17-Math.abs(z)-1;
				checkBuildTower(tile, x_new,z_new);
				return;
			}
		}
		if(tile=="BOTTOM_LEFT"){
			if(x<0&&z>0){
				int x_new= 17-Math.abs(x)-1;
				int z_new= Math.abs(z)-1;
				checkBuildTower(tile, x_new,z_new);
				return;
			}
		}
		if(tile=="BOTTOM_RIGHT"){
			if(x>0&&z>0){
				int x_new= Math.abs(x)-1;
				int z_new= Math.abs(z)-1;
				checkBuildTower(tile, x_new,z_new);
				return;
			}
			
		}
		buildTower=false;
	}
	

	private void checkBuildTower(String tile, int x, int y) {
		HashMap<String, Cell> checkBuild=model.getCells();
		for(Cell c: checkBuild.values()){
			if(c.getMap().getTile().getPosition().equals(tile)
					&&c.getX()==x
					&&c.getY()==y
					&&c.getType().contains("TOWER")){
				try {
					info=ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().getInfo();
					JsonSender.createTower(ObjectPath.tower(info.getTower_value()), c.getID());
				} catch (Exception e) {
				}
			}
		}
		
	}
	
	public void drawTower() {
		if (model.getTowers() == null) {
			return;
		}
		
		Element<Tower> next = model.getTowers().getHead();
		Tower t;
		while(next != null) {
			t = next.getE();
			if (t.getType() == null)
				return;
			tower.build(t.getType());
			if (colorPicking) {
				if(t.isBuilding() || t.isSelling()) {
					if(t.getColor() != null && t.getCell() != null) {
						drawTowerForColorPicking(tower.getObject(), tower.getColored(), t.getCell().getWorldX(), (float)t.getBuildProgress(), t.getCell().getWorldY());
					}
				} else {
					if(t.getColor() != null && t.getCell() != null) {
						drawTowerForColorPicking(tower.getObject(), tower.getColored(), t.getCell().getWorldX(), (float)t.getBuildProgress(), t.getCell().getWorldY());
					}
				}
			} else {
				if(t.isBuilding() || t.isSelling()) {
					if(t.getColor() != null && t.getCell() != null) {
						renderTower(tower.getObject(), tower.getColored(), t.getCell().getWorldX(), (float)t.getBuildProgress(), t.getCell().getWorldY(), t.getColor());
						
					}
				} else {
					if(t.getColor() != null && t.getCell() != null) {
						if(ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().getTowerToUpgrade() != null && ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().getTowerToUpgrade().getID().equals(t.getID())) {
							renderPickedTower(tower.getObject(), tower.getColored(), t.getCell().getWorldX(), t.getCell().getWorldY(), t.getColor(),t);
						} else {
							renderTower(tower.getObject(), tower.getColored(), t.getCell().getWorldX(), 1, t.getCell().getWorldY(), t.getColor());
						}
					}	
				}
			}
			
			next = next.getNext();
		}
	}
	
	private void renderPickedTowerRange(Tower t) {
		glDisable(GL_BLEND);
		glDisable(GL_LIGHTING);
		
		glPushMatrix();
		{
			glEnable(GL_BLEND);
			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
			glColor4f(1, 0, 0,0.5f);
			glTranslated(t.getCell().getWorldX(), 0.001, t.getCell().getWorldY());
			glRotatef(90, 1, 0, 0);
			rangeDiskIn.draw(0,(float) (t.getTowerDescription().getRange() * CELL_SIZE)-0.004f, 60, 1);
			glColor4f(0, 1, 0, 0.7f);
			rangeDiskOut.draw((float)(t.getTowerDescription().getRange() * CELL_SIZE)-0.004f ,(float) t.getTowerDescription().getRange() * CELL_SIZE, 60, 1);
			glDisable(GL_BLEND);
		}
		glPopMatrix();
		
		glEnable(GL_BLEND);
		glEnable(GL_LIGHTING);
	}
	
	private void renderPickedTower(Model object, Model colored, float worldX, float worldY, String color, Tower t) {		
		glPushMatrix();
		{
			glDisable(GL_LIGHTING);
			glDisable(GL_TEXTURE_2D);
			glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
			glEnable( GL_POLYGON_OFFSET_FILL );
			glPolygonOffset(-2.5f, -2.5f);
			glColor3f(1, 1, 1);
			glLineWidth(3f);
			
			renderPickedTower(object, colored, worldX, 1, worldY, color,t );
			
			glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
			glEnable(GL_LIGHTING);
			glEnable(GL_TEXTURE_2D);
			
			renderTower(object, colored, worldX, 1, worldY, color);
			
			
			glDisable(GL_POLYGON_OFFSET_FILL);
			glLineWidth(1f);
			
		}
		glPopMatrix();
		
		renderPickedTowerRange(t);
	}

	private void renderPickedTower(Model object, Model colorObject, float x, float y, float z, String color, Tower t){
		glPushMatrix();
		{
			glTranslatef(x, -1/8f + y/8f, z);
			glScalef(CELL_SIZE, CELL_SIZE, CELL_SIZE);
			glRotatef(90, 0, 1, 0);
			//glColor3f(1, 1, 1);
			setColor("ffffff");
			object.render();
			setColor(color);
			colorObject.render();
		}
		glPopMatrix();
	}
	
	private void renderTower(Model object, Model colorObject, float x, float y, float z, String color){
		glEnable(GL_TEXTURE_2D);
		glPushMatrix();
		{
			glTranslatef(x, -1/8f + y/8f, z);
			glScalef(CELL_SIZE, CELL_SIZE, CELL_SIZE);
			glRotatef(90, 0, 1, 0);
			//glColor3f(1, 1, 1);
			setColor("ffffff");
			object.render();
			setColor(color);
			colorObject.render();
		}
		glPopMatrix();
		glDisable(GL_TEXTURE_2D);
	}
	
	public void setColor(String color) {
		material.put(0, 0.3f * Integer.parseInt(color.substring(0, 1),16) / 15f);
		material.put(1, 0.3f * Integer.parseInt(color.substring(2, 3),16) / 15f);
		material.put(2, 0.3f * Integer.parseInt(color.substring(4, 5),16) / 15f);
		material.put(3, 1);
		
		material.rewind();
		glMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, material);
	}
	
	public void drawCreep(float timeElapsed) {
		if (model.getCreeps() == null) {
			return;
		}

		model = ingameFunctions.getGui().getStart().getLogic().getManager();
		Element<Creep> next = model.getCreeps().getHead();
		Creep c;
		while (next != null) {
			c = next.getE();
			if (c.getCell() != null) {
				if (c.getType() != null) {
					updateCreep(c, timeElapsed);

					creep.build(c.getType());
					if (c.getCurrentWaypoint() != null) {
						rotateCreep = c.getCurrentWaypoint().getRotateUnit();
					}
					if (creep.getObject() != null) {
						renderCreep(creep.getObject(), c.getWorldX(), c.getWorldZ());
					}
				}
			}
			next = next.getNext();
		}
	}
	
	private void updateCreep(Creep c, float timeElapsed) {
		c.addToWalkedDistance(timeElapsed);
		
		if(c.getCurrentWaypoint() == null) {
			return;
		}
		
		float curDistance = (float)(c.getCurrentWaypoint().getWayToPoint() * c.getWalkedDistance() * c.getSpeed() / 1000);
		
		if(curDistance > c.getCurrentWaypoint().getWayToPoint()) {
			c.setWorldX(c.getCurrentWaypoint().getWorldX() + c.getVector()[0] * c.getCurrentWaypoint().getWayToPoint());
			c.setWorldZ(c.getCurrentWaypoint().getWorldY() + c.getVector()[1] * c.getCurrentWaypoint().getWayToPoint());
		} else {
			c.setWorldX(c.getCurrentWaypoint().getWorldX() + c.getVector()[0] * curDistance);
			c.setWorldZ(c.getCurrentWaypoint().getWorldY() + c.getVector()[1] * curDistance);
		}
	}
	
	private void renderCreep(Model creep, float x , float z){
		glEnable(GL_TEXTURE_2D);
		glColor3f(1, 1, 1);
		glPushMatrix();
		{

			glTranslatef(x, 0, z);
			glScalef(CELL_SIZE, CELL_SIZE, CELL_SIZE);
			glRotatef(rotateCreep, 0, 1, 0);
			setColor("ffffff");
			creep.render();
			
		}
		glPopMatrix();
		glDisable(GL_TEXTURE_2D);
	}
	
	
	private void drawTowerForColorPicking(Model object, Model colored, float x, float y, float z){
		glPushMatrix();
		{
			glColor3f((x + 1)/2f, (z + 1)/2f, 0);
			glTranslatef(x, -1/8f + y/8f, z);
			glScalef(CELL_SIZE, CELL_SIZE, CELL_SIZE);
			glRotatef(90, 0, 1, 0);
			object.render();
			colored.render();
		}
		glPopMatrix();
	}
	    
	public void drawPickingMode() {
		colorPicking = true;
		boolean texturing = glIsEnabled(GL_TEXTURE_2D);
		glDisable(GL_TEXTURE_2D);
		glDisable(GL_DITHER);
			drawTower();
			renderFieldsForColorPicking();
		glEnable(GL_DITHER);
		if(texturing) {
			glEnable(GL_TEXTURE_2D);
		}
		colorPicking = false;
	}

	public void renderFieldsForColorPicking() {
		try {
			HashMap<String, Cell> cells = model.getCells();
			for (Cell c : cells.values()) {
				int x = c.getX();
				int y = c.getY();
				float xField=0;
				float yField=0;
				if(c.getMap().getTile().getPosition().contains("TOP_LEFT")){
					xField=((x-16)*(1/16f))+(1/32f);
					yField=-((16-y)*(1/16f))+(1/32f);
				}
				if(c.getMap().getTile().getPosition().contains("TOP_RIGHT")){
					xField=((x)*(1/16f))+(1/32f);
					yField=-((16-y)*(1/16f))+(1/32f);
				}
				if(c.getMap().getTile().getPosition().contains("BOTTOM_LEFT")){
					xField=((x-16)*(1/16f))+(1/32f);
					yField=((y)*(1/16f))+(1/32f);
				}
				if(c.getMap().getTile().getPosition().contains("BOTTOM_RIGHT")){
					xField=((x)*(1/16f))+(1/32f);
					yField=((y)*(1/16f))+(1/32f);
				}
				drawPickingField(xField, yField, c.getMap().getTile().getPosition());
			}

		} catch (Exception e) {
		}
	}
	
	private void drawPickingField(float x, float y, String position) {
		glPushMatrix();
		{
			glColor3f((x + 1)/2f, (y + 1)/2f, 0);
			glScalef(1 / 2f, 1 / 2f, 1 / 2f);
			glTranslatef(x, 0, y);
			glBegin(GL_QUADS);
			{
				glVertex3f(x-1/16f, 0, y-1/16f);
				glVertex3f(x-1/16f, 0, y+1/16f);
				glVertex3f(x+1/16f, 0, y+1/16f);
				glVertex3f(x+1/16f, 0, y-1/16f);
			}
			glEnd();
			
		}
		glPopMatrix();
	}
	

	public void checkCell(int x, int z) {
		if(!ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().getGameOver()) {
			if(x < 0 && z < 0){
			    //TOP_LEFT		
				int x_new= 17-Math.abs(x)-1;
				int z_new= 17-Math.abs(z)-1;
				HashMap<String, Cell> checkBuild=model.getCells();
				for(Cell c: checkBuild.values()){
					if(c.getMap().getTile().getPosition().equals("TOP_LEFT")) {
						if(c.getX() == x_new && c.getY() == z_new) {
							if(c.getTower() != null) {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().enableTowerUpgradeWindow(c.getTower(), "TOP_LEFT");
							} else {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().disableTowerUpgradeWindow();
							}
						}
					}
				}
			} else if(z < 0 && x > 0){
				//TOP_RIGHT	
				int x_new= Math.abs(x)-1;
				int z_new= 17-Math.abs(z)-1;
				HashMap<String, Cell> checkBuild=model.getCells();
				for(Cell c: checkBuild.values()){
					if(c.getMap().getTile().getPosition().equals("TOP_RIGHT")) {
						if(c.getX() == x_new && c.getY() == z_new) {
							if(c.getTower() != null) {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().enableTowerUpgradeWindow(c.getTower(), "TOP_RIGHT");
							} else {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().disableTowerUpgradeWindow();
							}
						}
					}
				}
			} else if(x < 0 && z > 0){
				//BOTTOM_LEFT
				int x_new= 17-Math.abs(x)-1;
				int z_new= Math.abs(z)-1;
				HashMap<String, Cell> checkBuild=model.getCells();
				for(Cell c: checkBuild.values()){
					if(c.getMap().getTile().getPosition().equals("BOTTOM_LEFT")) {
						if(c.getX() == x_new && c.getY() == z_new) {
							if(c.getTower() != null) {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().enableTowerUpgradeWindow(c.getTower(), "BOTTOM_LEFT");
							} else {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().disableTowerUpgradeWindow();
							}
						}
					}
				}
			} else {
				//BOTTOM_RIGHT
				int x_new= Math.abs(x)-1;
				int z_new= Math.abs(z)-1;
				HashMap<String, Cell> checkBuild=model.getCells();
				for(Cell c: checkBuild.values()){
					if(c.getMap().getTile().getPosition().equals("BOTTOM_RIGHT")) {
						if(c.getX() == x_new && c.getY() == z_new) {
							if(c.getTower() != null) {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().enableTowerUpgradeWindow(c.getTower(), "BOTTOM_RIGHT");
							} else {
								ingameFunctions.getGui().getIngameScreen().getIngameScreenHUD().getController().disableTowerUpgradeWindow();
							}
						}
					}
				}
			}
		}
	}
	
	


	public void clickedField(int pickX, int pickZ) {
		tile(pickX, pickZ);
		this.pickX=pickX;
		this.pickZ=pickZ;
	}

	public boolean isBuildTower() {
		return buildTower;
	}

	public void setBuildTower(boolean buildTower) {
		this.buildTower = buildTower;
	}


	public void setShowCells(boolean showCells) {
		this.showCells = showCells;
	}

	public void setPick(int pickX, int pickZ) {
		this.pickX = pickX;
		this.pickZ = pickZ;
	}
	
	public void unsetPick() {
		pickX = -30;
		pickZ = -30;
	}

	public int getMousePosX() {
		return mousePosX;
	}

	public void setMousePosX(int mousePosX) {
		this.mousePosX = mousePosX;
	}

	public int getMousePosZ() {
		return mousePosZ;
	}

	public void setMousePosZ(int mousePosZ) {
		this.mousePosZ = mousePosZ;
	}
	
	public void setModel_object(Model model_object) {
		this.model_object = model_object;
	}
	
	public void setModel_colored(Model model_colored) {
		this.model_colored = model_colored;
	}

	public void setTextureFile(File textureFile) {
		this.textureFile = textureFile;
	}
	public boolean isTowerChoosed() {
		return towerChoosed;
	}
	public void setTowerChoosed(boolean value){
		this.towerChoosed=value;
	}
	public int getPickX() {
		return pickX;
	}
	public int getPickZ() {
		return pickZ;
	}
	
	public float getQ1() {
		return q1;
	}

	public void setQ1(float q1) {
		this.q1 = q1;
	}
	
	public float getQ2() {
		return q2;
	}

	public void setQ2(float q2) {
		this.q2 = q2;
	}
	public float getQ3() {
		return q3;
	}

	public void setQ3(float q3) {
		this.q3 = q3;
	}
	public float getQ4() {
		return q4;
	}

	public void setQ4(float q4) {
		this.q4 = q4;
	}
	
	public void selectedTower(String towerName){
		this.selectedTower=towerName;
	}
	
}